package edu.fudan.jwxt.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.fudan.jwxt.Exception.ServiceException;
import edu.fudan.jwxt.common.Constants;
import edu.fudan.jwxt.dao.ClassTimeDao;
import edu.fudan.jwxt.dao.CourseTimeVODao;
import edu.fudan.jwxt.entity.ClassTime;
import edu.fudan.jwxt.entity.VO.CourseTimeVO;
import edu.fudan.jwxt.service.ClassTimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.sql.Time;
import java.util.Collection;
import java.util.List;

@Service
public class ClassTimeServiceImpl extends ServiceImpl<ClassTimeDao, ClassTime> implements ClassTimeService {

    @Autowired
    private ClassTimeDao classTimeDao;

    @Autowired
    private CourseTimeVODao courseTimeVODao;

    @Override
    public boolean save(ClassTime entity) {
        Time endTime = entity.getEndTime();
        int count = (int) count();   //数据库总记录数

        //检查时间的可行性
        TimeCheck(entity,true);

        //找出所有开始时间大于该课结束时间的课节
        LambdaQueryWrapper<ClassTime> q = new LambdaQueryWrapper<>();
        q.gt(ClassTime::getStartTime,endTime);
        List<ClassTime> classTimeList = list(q);

        //设置id
        if(count == 0){
            entity.setId(1);
        }else if(classTimeList.isEmpty()){
            entity.setId(count + 1);
        }else{
            int id = classTimeList.get(0).getId();
            for (int i = classTimeList.size() - 1; i >= 0; i--){
                int oldId = classTimeList.get(i).getId();
                classTimeDao.updateId(oldId,oldId + 1);
            }
            entity.setId(id);
        }


        return super.save(entity);
    }

    @Override
    public boolean updateById(ClassTime entity) {

        if(getById(entity.getId()) == null)
            return false;

        TimeCheck(entity,false);
        //额外判断更新时的情况，即改变时间后它的次序不能变
        //找出所有开始时间小于该课结束时间的课节
        LambdaQueryWrapper<ClassTime> q = new LambdaQueryWrapper<>();
        q.lt(ClassTime::getEndTime,entity.getStartTime());
        long classTimeCount = count(q);


        if(entity.getId() != classTimeCount + 1)
            throw new ServiceException(Constants.CODE_600,"时间超出选择范围");

        return super.updateById(entity);
    }

    @Override
    public boolean removeById(Serializable id) {
        ClassTime classTime = getById(id);

        if(classTime == null)
            return false;

        LambdaQueryWrapper<CourseTimeVO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseTimeVO::getTimeId,id);
        long count = courseTimeVODao.selectCount(queryWrapper);
        if(count != 0)
            throw new ServiceException(Constants.CODE_600,"该时间下有开设课程");

        //找出所有开始时间大于该课结束时间的课节
        LambdaQueryWrapper<ClassTime> q = new LambdaQueryWrapper<>();
        q.gt(ClassTime::getStartTime,classTime.getEndTime());
        List<ClassTime> classTimeList = list(q);
        //删除
        super.removeById(id);

        //次序更新
        for (ClassTime c : classTimeList){
            int oldId = c.getId();
            classTimeDao.updateId(oldId,oldId - 1);
        }

        return true;
    }



    @Override
    public boolean removeByIds(Collection<?> list) {
        for(Object obj : list){
            ClassTime classTime = (ClassTime) obj;
            LambdaQueryWrapper<CourseTimeVO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CourseTimeVO::getTimeId,classTime.getId());
            long count = courseTimeVODao.selectCount(queryWrapper);
            if(count != 0)
                throw new ServiceException(Constants.CODE_600,"部分时间存在开设课程，无法进行删除");
        }

         boolean flag =  super.removeByIds(list);
         //删除后进行排序
        List<ClassTime> classTimeList = list();
        for(int i = 0; i < classTimeList.size(); i++){
            classTimeDao.updateId(classTimeList.get(i).getId(),i+1);
        }
        return flag;
    }

    //检查添加或更新时间的可行性
    private void TimeCheck(ClassTime entity,boolean save){
        Time startTime = entity.getStartTime();
        Time endTime = entity.getEndTime();



        if(endTime.compareTo(startTime) <= 0)
            throw new ServiceException(Constants.CODE_600,"开始时间不能晚于结束时间");

        //查找是否存在与该课节时间端冲突的课节
        LambdaQueryWrapper<ClassTime> queryWrapper = new LambdaQueryWrapper<>();
        if (save)   //添加
            queryWrapper.between(ClassTime::getStartTime,startTime,endTime);
        else    //更新
            queryWrapper.between(ClassTime::getStartTime,startTime,endTime).ne(ClassTime::getId,entity.getId());

        List<ClassTime> contradiction1 = list(queryWrapper);
        queryWrapper.clear();
        if(save)
            queryWrapper.between(ClassTime::getEndTime,startTime,endTime);
        else
            queryWrapper.between(ClassTime::getEndTime,startTime,endTime).ne(ClassTime::getId,entity.getId());

        List<ClassTime> contradiction2 = list(queryWrapper);

        if(!contradiction1.isEmpty() || !contradiction2.isEmpty())
            throw new ServiceException(Constants.CODE_600,"时间存在冲突");

    }

}
